Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up server side row model for table visualization #12272

Open
wants to merge 46 commits into
base: develop
Choose a base branch
from

Conversation

marthasharkey
Copy link
Contributor

@marthasharkey marthasharkey commented Feb 13, 2025

Pull Request Description

Introduces the server side row model to appropriate table visualizations.

Creates an extra get_rows_for_table method that gets the row data rather than this being serialised in the existing prepare visualization step.
Adds method to visualisationConfig to allow the visualization to execute and expression to access this method.

prepare_vizualization still gets column definition information and largely remains the same
get_rows_for_table sorts and filters the table and returns the correct rows for the visualization.

TableViz behaviour remains mostly the same but filtering/soring large tables is no longer blocked:
ag-grid-ssrm-3

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.
  • If meaningful changes were made to logic or tests affecting Enso Cloud integration in the libraries,
    or the Snowflake database integration, a run of the Extra Tests has been scheduled.
    • If applicable, it is suggested to paste a link to a successful run of the Extra Tests.

Copy link

github-actions bot commented Feb 13, 2025

🧪 Storybook is successfully deployed!

📊 Dashboard:

@marthasharkey marthasharkey marked this pull request as ready for review March 4, 2025 18:16
Comment on lines +310 to +323
executeExpression: (
visulizationModule: string,
expressionString: string,
formatFunction:
| ((arg: any, tempModule: Ast.MutableModule) => Ast.Owned<Ast.MutableExpression>)
| null,
...positionalArgumentsExpressions: string[]
) =>
executeExpression(
visulizationModule,
expressionString,
formatFunction,
...positionalArgumentsExpressions,
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary lambda.

Comment on lines +199 to +208
function setRowLimit(newRowLimit: number) {
if (newRowLimit !== rowLimit.value) {
rowLimit.value = newRowLimit
config.setPreprocessor(
'Standard.Visualization.Table.Visualization',
'prepare_visualization',
newRowLimit.toString(),
)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Vue pattern for this is to set rowLimit.value directly, and run the side-effect as needed via a watcher, like watchEffect(() => config.setPreprocessor('Standard.Visualization.Table.Visualization', 'prepare_visualization', rowLimit.value.toString())).

@@ -92,6 +95,50 @@ export function useVisualizationData({
},
)

const executeExpression = async (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this function is part of the API for visualizations, its signature should be as simple as possible, and shouldn't contain any any types. I think it could be generalized to: executeExpression(expression: (nodeOutputIdentifier: string) => string): Promise<Result<unknown> | null>. The logic for constructing the expression (L116-L140) can be left to the caller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I did think it had started to get too specific for this usecase, thank you

all_rows = ["all_rows_count", all_rows_count]
has_index_col = ["has_index_col", include_index_col]
has_index_col = ["has_index_col", True]
is_ssrm = if is_db_table then False else all_rows_count > max_rows
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO it may be better to spell out what SSRM is here as it is not that obvious IMO when looking at the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I agree, ssrm is a ag grid term so I'll change it to be more descriptive

Comment on lines 219 to 227
applies the sort model to the table.

Arguments:
- start_number: the start index of the next 100 rows to get
- sort_col_index_list: indexes of columns with sorts applies
- sort_direction_list: list of sort directions 1 for ascending -1 for descending

get_distinct_values_for_column : Table -> Integer -> JS_Object
get_distinct_values_for_column x column_index =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment is not aligned with the method that it is documenting, perhaps copied from apply_sort_to_table.

Arguments:
- table: table to sort
- filter_col: indexes of columns with sorts applies
- filter_action: list of filter actions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused - the comment here says that this is a list of actions but the type signature says Filter_Condition - indicating a single value not a list. Looking at the code it is not a list, so perhaps this comment became outdated?

Comment on lines 261 to 265
result = case filter_action of
Filter_Condition.Between _ _ _ -> table.filter (filter_col+1) (Filter_Condition.Between filter_val filter_to_val)
Filter_Condition.Is_In _ _ -> if filter_val.length > 0 then table.filter (filter_col+1) (Filter_Condition.Is_In filter_val) else table.filter filter_col (Filter_Condition.Is_In [""])
_ -> table.filter (filter_col+1) (filter_action (filter_val))
result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very minor nitpick but the result is assigned just to be returned, isn't it better to just remove result = and return the case of directly?

This should have equivalent behaviour:

Suggested change
result = case filter_action of
Filter_Condition.Between _ _ _ -> table.filter (filter_col+1) (Filter_Condition.Between filter_val filter_to_val)
Filter_Condition.Is_In _ _ -> if filter_val.length > 0 then table.filter (filter_col+1) (Filter_Condition.Is_In filter_val) else table.filter filter_col (Filter_Condition.Is_In [""])
_ -> table.filter (filter_col+1) (filter_action (filter_val))
result
case filter_action of
Filter_Condition.Between _ _ _ -> table.filter (filter_col+1) (Filter_Condition.Between filter_val filter_to_val)
Filter_Condition.Is_In _ _ -> if filter_val.length > 0 then table.filter (filter_col+1) (Filter_Condition.Is_In filter_val) else table.filter filter_col (Filter_Condition.Is_In [""])
_ -> table.filter (filter_col+1) (filter_action (filter_val))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I think I potentially has this while writing the function and forgot to go back and simplify

Comment on lines +293 to +295
get_rows_for_table x start_number sort_col_index_list=Nothing sort_direction_list=Nothing filter_col=Nothing filter_action=Nothing filter_val=Nothing filter_extra_val=Nothing =
max_rows=100
col_name = x.make_temp_column_name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a nitpick but why sometimes use table for a table argument and sometimes just x?

I think we should consistently use table in these functions. It makes the code clearer to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I agree, I thought I had updates all to table but must have missed this one!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants